
'''
@author: Rocio
'''

from clasesPrincipales.Instruccion import Instruccion
from clasesPrincipales.Kernel import Kernel
from clasesPrincipales.Signal import Signal
from datetime import time
import threading
class CPU(threading.Thread):
    
###############################################################################################################

    #INICIALIZACION
    #La cpu es un threads, recibe al kernel, para q este le indique 
    #cuando detenerse
    def __init__(self,kernel, memoria ) :
        threading.Thread.__init__(self)
        self.pc = None # program counter
        self.elKernel = Kernel
        self.memoria = memoria


###############################################################################################################

    #METODOS
    def run(self):
        while self.elKernel.getRunning():
            self.execute

    def execute(self):       
            if self.pc is not None:
                instr = self.memory.read(self.pc)
                self.tipoInstruccion(instr)
            else:
                time.sleep(0.1) # idle
                
    def tipoInstruccion (self, instr):
        if instr is None:
            self.kernel.interrupt(Signal.EXIT)
        elif instr.opcode is Instruccion.CPU:
            self.pc = self.pc[0], self.pc[1]
            self.ejecutarInstrCpu(instr)
        elif instr.opcode is Instruccion.IO:
            print('[io] %s - %s' % (instr, self.pc))
            self.pc = self.pc[0], self.pc[1] + 1
            self.kernel.interrupt(Signal.IO_REQ)
        else:
            self.kernel.interrupt(Signal.KILL)
    
    # RO hice este metodo para que no quedara feo. Me parece feo que haya un while dentro d un if je
    def ejecutarInstrCpu (self, instr):
        while not self.elkernel.getKernelMode() and self.pc[2] > 0:
            print('[cpu] %s - %s' % (instr, self.pc))
            time.sleep(0.5) 
            self.pc = self.pc[0], self.pc[1] + 1